10082. Shortest even path
Undirected
unweighted graph is given. Find the shortest path between two vertices of even
length.
Input. The first line contains four integers:
number of vertices n, number of edges
m (n, m ≤ 105),
source s and destination d (1 ≤ s, d ≤ n). Each of the
next m lines contains two integers a and b describing an undirected edge (a, b).
Output. Print the shortest distance from s to d. The length of the path (number of edges in the path) must be
even. If there is no path of even length between s and d,
print -1.
Sample
input 1 |
Sample
output 1 |
8 8 1 6 1 2 2 3 3 4 4 5 5 6 4 7 7 8 8 6 |
6 |
|
|
Sample
input 2 |
Sample
output 2 |
6 5 1 6 1 2 2 3 3 4 4 5 5 6 |
-1 |
graphs - bfs
Split each vertex
v of the graph into two: v1
and v2. For each
undirected edge (u, v) create two undirected edges (u1,
v2) and (u2, v1).
For example, the
vertex v can be associated with vertices 2 * v – 1 and 2 * v.
The shortest
path between the vertices 2 * s – 1 and 2 * d – 1 will be the desired one and will have an even length.
Consider next
sample graph and splitted graph:
Let we start bfs
from the vertex v = 11. Then
·
if we’ll arrive to the vertex x1, the length of the path will be even;
·
if we’ll arrive to the vertex x2, the length of the path will be odd;
Finding the shortest path
of even length from 1 to 4 in the original
graph is equivalent to finding the shortest path from 11 to 41 (or from 1 to 7) in the
splitted graph.
Example
The graph in the
first example is shown on the left. The even shortest path is highlighted. In
the second example (picture on the right), there is no path of even length
between vertices 1 and 6.
Declare an adjacency list g of
the graph and an array of shortest distances dist.
vector<vector<int>
> g;
vector<int>
dist;
Function bfs implements breadth first search from the vertex start.
void bfs(int start)
{
queue<int>
q;
q.push(start);
while
(!q.empty())
{
int v =
q.front(); q.pop();
for (int i =
0; i < g[v].size(); i++)
{
int to =
g[v][i];
if
(dist[to] == -1)
{
q.push(to);
dist[to] =
dist[v] + 1;
}
}
}
}
The main part of the program. Read the input data.
scanf("%d %d %d %d",
&n, &m, &s, &d);
g.resize(2*n + 1);
for (i = 0; i < m; i++)
{
scanf("%d
%d", &u, &v);
Read the edge (u, v). Split each of the vertices u and v into two. Create the edges (2*u, 2*v
– 1) and (2* v, 2*u – 1).
g[2*u].push_back(2*v-1);
g[2*v-1].push_back(2*u);
g[2*v].push_back(2*u-1);
g[2*u-1].push_back(2*v);
}
After splitting, the number of
vertices doubles.
n = 2 * n;
Initialize the array of shortest
distances.
dist = vector<int>(n
+ 1, -1);
dist[2*s-1] = 0;
Start the breadth first search from the start vertex.
bfs(2*s-1);
Print the answer.
printf("%d\n",
dist[2*d-1]);
import java.util.*;
public class Main
{
static
ArrayList<Integer>[] g;
static int dist[];
static void bfs(int start)
{
Arrays.fill(dist,-1);
dist[start] =
0;
Queue<Integer> q = new
LinkedList<Integer>();
q.add(start);
while(!q.isEmpty())
{
int v = q.poll();
for(int i = 0;
i < g[v].size();
i++)
{
int to = g[v].get(i);
if (dist[to] ==
-1)
{
q.add(to);
dist[to] = dist[v] +
1;
}
}
}
}
@SuppressWarnings("unchecked")
public static void
main(String[] args)
{
Scanner con = new
Scanner(System.in);
int n = con.nextInt();
int m = con.nextInt();
int s = con.nextInt();
int d = con.nextInt();
g = new
ArrayList[2*n+1];
for(int i = 0;
i <= 2*n; i++)
g[i] = new
ArrayList<Integer>();
for (int i = 0;
i < m; i++)
{
int u = con.nextInt();
int v = con.nextInt();
g[2*u].add(2*v-1);
g[2*v-1].add(2*u);
g[2*v].add(2*u-1);
g[2*u-1].add(2*v);
}
n = 2
* n;
dist = new int[n+1];
bfs(2*s-1);
System.out.println(dist[2*d-1]);
con.close();
}
}